home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
gnu
/
nihcl-30.lha
/
nihcl-3.0
/
vector
/
Vec.m4
< prev
next >
Wrap
Text File
|
1990-05-16
|
20KB
|
884 lines
/* Vec.m4 -- M4 code templates for NIHCL Vector classes
THIS SOFTWARE FITS THE DESCRIPTION IN THE U.S. COPYRIGHT ACT OF A
"UNITED STATES GOVERNMENT WORK". IT WAS WRITTEN AS A PART OF THE
AUTHOR'S OFFICIAL DUTIES AS A GOVERNMENT EMPLOYEE. THIS MEANS IT
CANNOT BE COPYRIGHTED. THIS SOFTWARE IS FREELY AVAILABLE TO THE
PUBLIC FOR USE WITHOUT A COPYRIGHT NOTICE, AND THERE ARE NO
RESTRICTIONS ON ITS USE, NOW OR SUBSEQUENTLY.
Author:
K. E. Gorlen
Bg. 12A, Rm. 2033
Computer Systems Laboratory
Division of Computer Research and Technology
National Institutes of Health
Bethesda, Maryland 20892
Phone: (301) 496-1111
uucp: uunet!nih-csl!kgorlen
Internet: kgorlen@alw.nih.gov
May, 1986
Function:
This file contains M4 macro definitions for almost all of the functions
needed to implement the NIHCL vector classes.
Modification History:
$Log: Vec.m4,v $
Revision 3.0 90/05/16 23:00:41 kgorlen
Release for 1st edition.
*/
// WARNING: Modify the M4 macros, not the C++ code they generate!
// WARNING: Assumes 8 bits per character.
define(CONCAT,$1$2$3$4$5$6$7$8$9)
define(CAP,`CONCAT(translit(substr($1,0,1),abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ),substr($1,1))')
define(PROLOGUE,
``#include'' "$1Vec.h"
``#include'' "nihclIO.h"
``#define'' THIS $1Vec
``#define'' BASE Vector
``#define'' BASE_CLASSES Vector::desc()
``#define'' MEMBER_CLASSES
``#define'' VIRTUAL_BASE_CLASSES
DEFINE_CLASS($1Vec,1,"$Header: /afs/alw.nih.gov/unix/sun4_40c/usr/local/src/nihcl-3.0/share/vector/RCS/Vec.m4,v 3.0 90/05/16 23:00:41 kgorlen Rel $",NULL,NULL);
typedef float Float;
typedef double Double;
typedef unsigned char Byte;
typedef short Short;
typedef int Int;
typedef long Long;
void $1Copy(const $1* src, $1* dst, unsigned long count)
// Copy n $1 elements from src to dst.
{
const $1* sp = src;
$1* dp = dst;
``#ifndef'' DUFF
unsigned long n = count;
while (n--) *dp++ = *sp++;
``#else''
// Unrolled loop using Duff's Device:
unsigned long n = (count+7)>>3;
switch (count & 7) {
case 0: do { *dp++ = *sp++;
case 7: *dp++ = *sp++;
case 6: *dp++ = *sp++;
case 5: *dp++ = *sp++;
case 4: *dp++ = *sp++;
case 3: *dp++ = *sp++;
case 2: *dp++ = *sp++;
case 1: *dp++ = *sp++;
} while (--n > 0);
}
``#endif''
}
void Temp$1Vec::free() { delete this; }
bool $1Vec::isEqual(const Object& u) const
// Test $1Vecs equal.
{
const $1Vec* U = castdown(&u);
if (!u.isSpecies(classDesc) || n!=U->n) return NO;
unsigned i = n;
$1* vp = v;
$1* up = U->v;
while (i--) if (*vp++ != *up++) return NO;
return YES;
}
const Class* $1Vec::species() const { return &classDesc; }
void $1Vec::deepenShallowCopy() {}
$1Vec::$1Vec(OIOin& strm) : BASE(strm)
{
v = new $1[n];
strm.get(v,n);
}
void $1Vec::storer(OIOout& strm) const
{
Vector::storer(strm);
strm.put(v,n);
}
$1Vec::$1Vec(OIOifd& fd) : BASE(fd)
{
v = new $1[n];
fd.get(v,n);
}
void $1Vec::storer(OIOofd& fd) const
{
Vector::storer(fd);
fd.put(v,n);
}
extern const int NIHCL_INDEXRANGE;
extern const int NIHCL_SLICERANGE;
extern const int NIHCL_VECTORLENGTH;
extern const int NIHCL_VECTORSELECT;
void $1Vec::indexRangeErr() const
{
setError(NIHCL_INDEXRANGE,DEFAULT,this,className());
}
void $1Vec::selectErr(const BitVec& V) const
{
setError(NIHCL_VECTORSELECT,DEFAULT,this,"$1Vec",length(),sum(V),&V,V.length());
}
void $1Slice::selectErr(const BitVec& V) const
{
NIHCL::setError(NIHCL_VECTORSELECT,DEFAULT,this,"$1Slice",length(),sum(V),&V,V.length());
}
)
define(TYPE1_lengthErr_TYPE2,
void $1::lengthErr(const $2& V) const
{
NIHCL::setError(NIHCL_VECTORLENGTH,DEFAULT,this,"$1",length(),&V,"$2",V.length());
}
)
define(TYPEVec_CTOR_I,
$1Vec::$1Vec(unsigned lngth) : BASE(lngth)
// Construct an uninitialized $1Vec of the length specified.
{
v = NULL;
if (lngth != 0) v = new $1[lngth];
}
)
define(TYPEVec_CTOR_I_TYPE_TYPE,
$1Vec::$1Vec(unsigned lngth, $1 from, $1 by) : BASE(lngth)
// Construct a $1Vec of the length specified and initialize it to
// (v[0] = from, v[i] = v[i-1]+by for i = 1...n-1)
{
v = NULL;
if (lngth != 0) {
v = new $1[lngth];
$1* vp =v;
for ($1 x =from; lngth-- >0; x += by) *vp++ = x;
}
}
)
define(TYPEVec_CTOR_TYPEPTR_I,
$1Vec::$1Vec(const $1* src, unsigned lngth) : BASE(lngth)
// Construct a $1Vec and initialize it from the specified $1 vector.
{
v = NULL;
if (lngth != 0) {
v = new $1[lngth];
$1Copy(src,v,lngth);
}
}
)
define(TYPEVec_CTOR_TYPEVec,
$1Vec::$1Vec(const $1Vec& U) : BASE(U.n)
// Construct a $1Vec and initialize it from the specified $1Vec U.
{
v = NULL;
if (n != 0) {
v = new $1[n];
$1Copy(U.v,v,n);
}
}
)
define(TYPEVec_CTOR_TYPESlice,
$1Vec::$1Vec(const $1Slice& s) : BASE(s.length())
// Construct a $1Vec from a slice of another $1Vec.
{
v = NULL;
if (n != 0) {
v = new $1[n];
const $1* sp = s.pt();
$1* dp = v;
int i = s.length();
int j = s.stride();
while (i--) { *dp++ = *sp; sp += j; }
}
}
)
define(TYPESlice_CTOR_TYPEVec_I_I_I,
$1Slice::$1Slice(const $1Vec& v, int pos, unsigned lgt, int stride)
// Construct a $1Slice from a $1Vec.
{
if ((unsigned)(pos + (lgt-1)*stride) >= v.length())
NIHCL::setError(NIHCL_SLICERANGE,DEFAULT,&v,v.className(),v.length(),pos,lgt,stride);
V = &($1Vec&)v; p = &(($1Vec&)v)[pos]; l = lgt; k = stride;
}
)
define(TYPESlice_CTOR_TYPEPick,
$1Slice::$1Slice(const $1Pick& s)
// Construct a $1Vec slice from IntVec-subscripted elements of $1Vec.
// Can't do this with $1Slct::operator $1Slice() because of Temp$1Vec
{
$1Vec& T = *new Temp$1Vec();
T = (*s.V)[*s.X];
V = &T; p = T.pt(); l = T.length(); k = 1;
}
)
define(TYPESlice_CTOR_TYPESlice,
$1Slice::$1Slice(const $1Slice& s)
// Private $1Slice copy constructor
{
V = s.V;
p = s.p;
l = s.l;
k = s.k;
}
)
define(TYPESlice_CTOR_TYPESlct,
$1Slice::$1Slice(const $1Slct& s)
// Construct a $1Vec slice from $1Vec-selected elements of $1Vec.
// Can't do this with $1Slct::operator $1Slice() because of Temp$1Vec
{
$1Vec& T = *new Temp$1Vec();
T = (*s.V)[*s.B];
V = &T; p = T.pt(); l = T.length(); k = 1;
}
)
define(TYPEVec_ASN_TYPEVec,
void $1Vec::operator=(const $1Vec& U)
// Assign the argument $1Vec U to this $1Vec.
{
if (v != U.v) {
delete v;
v = NULL;
if ((n = U.n) != 0) {
v = new $1[n];
$1Copy(U.v,v,n);
}
}
}
)
define(TYPEVec_ASN_TYPESlice,
void $1Vec::operator=(const $1Slice& s)
// Assign a slice of a $1Vec to this $1Vec.
{
int i = s.length(); // slice length
if ((n = i) == 0) { // empty slice
delete v;
v = NULL;
return;
}
const $1* sp = s.pt();
int j = s.stride();
if (this == s.V) { // V = V(i,j,k)
$1* t = v;
$1* dp = new $1[i];
v = dp;
while (i--) { *dp++ = *sp; sp += j; }
delete t;
}
else {
delete v;
$1* dp = new $1[i];
v = dp;
while (i--) { *dp++ = *sp; sp += j; }
}
}
)
define(TYPEVec_ASN_TYPESlct,
void $1Vec::operator=(const $1Slct& s)
// Assign the BitVec-selected elements of a $1Vec to this $1Vec.
{
if ((n = sum(*s.B)) == 0) { // return zero length result
delete v;
v = NULL;
return;
}
$1* sp = s.V->pt();
$1* t = v;
if (this != s.V) delete t; // not V = V[BitVec&]
$1* dp = new $1[n];
v = dp;
BITVECSCAN(*s.B, s.length(), *dp++ = *sp; sp++)
if (this == s.V) delete t; // case V = V[BitVec&]
}
)
define(TYPEVec_ASN_TYPEPick,
void $1Vec::operator=(const $1Pick& s)
// Assign the IntVec-subscripted elements of a $1Vec to this $1Vec.
{
unsigned i = s.length();
unsigned l;
if ((l = i) == 0) { // return zero length result
delete v;
v = NULL; n = 0;
return;
}
$1* t = v;
if (this != s.V) delete t; // not V = V[IntVec&]
$1* dp = new $1[l];
$1* u = dp;
const int* xp = (*s.X).pt();
$1Vec& S = *s.V;
while (i--) { *dp++ = S[*xp++]; }
v = u; n = l;
if (this == s.V) delete t; // case V = V[IntVec&]
}
)
define(TYPEVec_ASN_TYPE,
void $1Vec::operator=($1 scalar)
// Assign a scalar to all elements of this $1Vec.
{
unsigned i = n;
$1* dp = v;
$1 c = scalar;
while (i--) *dp++ = c;
}
)
define(TYPESlice_ASN_TYPEVec,
void $1Slice::operator=(const $1Vec& U)
// Assign a $1Vec to this $1Vec slice.
{
int i = l;
if (i != U.length()) lengthErr(U);
$1* dp = p;
const $1* sp = U.pt();
int j = k;
while (i--) { *dp = *sp++; dp += j; }
}
)
define(TYPESlice_ASN_TYPESlice,
void $1Slice::operator=(const $1Slice& s)
// Assign a $1Vec slice to this $1Vec slice.
{
int i = l;
if (i != s.l) lengthErr(s);
$1* dp = p;
$1* sp = s.p;
int dj = k;
int sj = s.k;
while (i--) { *dp = *sp; dp += dj; sp += sj; }
}
)
define(TYPESlice_ASN_TYPEPick,
void $1Slice::operator=(const $1Pick& s)
// Assign the IntVec-subscripted elements of a $1Vec to this $1Vec slice.
{
int i = l;
if (i != s.length()) lengthErr(*s.X);
$1* dp = p;
const int* xp = (*s.X).pt();
int j = k;
$1Vec& S = *s.V;
while (i--) { *dp = S[*xp++]; dp += j; }
}
)
define(TYPESlice_ASN_TYPESlct,
void $1Slice::operator=(const $1Slct& s)
// Assign the BitVec-selected elements of a $1Vec to this $1Vec slice.
{
if (l != sum(*s.B)) lengthErr(s);
$1* sp = s.V->pt();
$1* dp = p;
int j = k;
BITVECSCAN(*s.B, s.length(), { *dp = *sp; dp += j; }; sp++)
}
)
define(TYPESlice_ASN_TYPE,
void $1Slice::operator=($1 scalar)
// Assign a scalar to all elements of this $1Vec slice.
{
int i = l;
int j = k;
$1* dp = p;
$1 c = scalar;
while (i--) { *dp = c; dp += j; }
}
)
define(FRIEND_OP_TYPESlice__TYPEVec,
$1Vec operator$2(const $1Slice& s)
// Unary operator on $1Vec slice.
{
int i = s.length();
$1Vec T(i);
const $1* sp = s.pt();
$1* dp = T.pt();
int j = s.stride();
while (i--) { *dp++ = $2(*sp); sp += j; }
return T;
}
)
define(FRIEND_INCDECOP_TYPESlice__TYPEVec,
$1Vec operator$2($1Slice& s)
// Unary inc/dec operator on $1Vec slice.
{
int i = s.length();
$1Vec T(i);
$1* sp = s.pt();
$1* dp = T.pt();
int j = s.stride();
while (i--) { *dp++ = $2(*sp); sp += j; }
return T;
}
)
define(FRIEND_TYPESlice_OP_TYPESlice__TYPEVec,
$1Vec operator$2(const $1Slice& u, const $1Slice& v)
// Binary arithmetic operator on two $1Vec slices
{
int i = u.length();
if (i != v.length()) u.lengthErr(v);
$1Vec T(i);
const $1* up = u.pt();
const $1* vp = v.pt();
$1* dp = T.pt();
int uj = u.stride();
int vj = v.stride();
while (i--) { *dp++ = *up $2 *vp; up += uj; vp += vj; }
return T;
}
)
define(FRIEND_TYPESlice_OP_TYPE__TYPEVec,
$1Vec operator$2(const $1Slice& s, $1 scalar)
// Binary arithmetic operator on $1Vec slice and scalar.
{
int i = s.length();
$1Vec T(i);
const $1* sp = s.pt();
$1* dp = T.pt();
int j = s.stride();
$1 c = scalar;
while (i--) { *dp++ = *sp $2 c; sp += j; }
return T;
}
)
define(FRIEND_TYPE_OP_TYPESlice__TYPEVec,
$1Vec operator$2($1 scalar, const $1Slice& s)
// Binary arithmetic operator on scalar and $1Vec slice.
{
int i = s.length();
$1Vec T(i);
const $1* sp = s.pt();
$1* dp = T.pt();
int j = s.stride();
$1 c = scalar;
while (i--) { *dp++ = c $2 *sp; sp += j; }
return T;
}
)
define(FRIEND_TYPESlice_OP_TYPESlice__BitVec,
BitVec operator$2(const $1Slice& u, const $1Slice& v)
// Relational operator on two $1Vec slices.
{
if (u.length() != v.length()) u.lengthErr(v);
BitVec B(u.length());
const $1* up = u.pt();
const $1* vp = v.pt();
int uj = u.stride();
int vj = v.stride();
BITVECGEN(B.pt(), u.length(), *up $2 *vp, up += uj; vp += vj)
return B;
}
)
define(FRIEND_TYPESlice_OP_TYPE__BitVec,
BitVec operator$2(const $1Slice& s, $1 scalar)
// Relational operator on $1Vec slice and scalar.
{
BitVec B(s.length());
const $1* vp = s.pt();
int vj = s.stride();
$1 c = scalar;
BITVECGEN(B.pt(), s.length(), *vp $2 c, vp += vj)
return B;
}
)
define(FRIEND_TYPE_OP_TYPESlice__BitVec,
BitVec operator$2($1 scalar, const $1Slice& s)
// Relational operator on scalar and $1Vec slice.
{
BitVec B(s.length());
const $1* vp = s.pt();
int vj = s.stride();
$1 c = scalar;
BITVECGEN(B.pt(), s.length(), c $2 *vp, vp += vj)
return B;
}
)
define(FRIEND_TYPESlice_ASNOP_TYPESlice,
void operator$2($1Slice& u, const $1Slice& v)
// Assignment arithmetic operator on two $1Vec slices.
{
int i = u.length();
if (i != v.length()) u.lengthErr(v);
$1* up = u.pt();
const $1* vp = v.pt();
int uj = u.stride();
int vj = v.stride();
while (i--) { *up $2 *vp; up += uj; vp += vj; }
}
)
define(FRIEND_TYPESlice_ASNOP_TYPE,
void operator$2($1Slice& s, $1 scalar)
// Assignment arithmetic operator on scalar and $1Vec slice.
{
int i = s.length();
$1* dp = s.pt();
int j = s.stride();
$1 c = scalar;
while (i--) { *dp $2 c; dp += j; }
}
)
define(TYPEPick_ASN_TYPEVec,
void $1Pick::operator=(const $1Vec& U)
// Assign $1Vec to IntVec-subscripted elements of $1Vec.
{
int i = length();
if (i != U.length()) lengthErr(*X,U);
const int* xp = (*X).pt();
const $1* up = U.pt();
$1Vec& D = *V;
while (i--) { D[*xp++] = *up++; }
}
)
define(TYPEPick_ASN_TYPEPick,
void $1Pick::operator=(const $1Pick& s)
// Assign IntVec-subscripted elements of $1Vec to IntVec-subscripted elements of $1Vec.
{
int i = length();
if (i != s.length()) lengthErr(*X,*s.X);
const int* xp = (*X).pt();
const int* yp = (*s.X).pt();
$1Vec& D = *V;
$1Vec& S = *s.V;
while (i--) { D[*xp++] = S[*yp++]; }
}
)
define(TYPEPick_ASN_TYPESlct,
void $1Pick::operator=(const $1Slct& s)
// Assign BitVec-selected elements of $1Vec to IntVec-subscripted elements of $1Vec.
{
if (length() != sum(*s.B)) X->selectErr(*s.B);
const int* xp = (*X).pt();
const $1* sp = (*s.V).pt();
$1Vec& D = *V;
BITVECSCAN(*s.B, length(), D[*xp++] = *sp; sp++)
}
)
define(TYPEPick_ASN_TYPESlice,
void $1Pick::operator=(const $1Slice& s)
// Assign $1Vec slice to IntVec-subscripted elements of $1Vec.
{
int i = length();
if (i != s.length()) s.lengthErr(*X);
const int* xp = (*X).pt();
const $1* sp = s.pt();
int j = s.stride();
$1Vec& D = *V;
while (i--) { D[*xp++] = *sp; sp += j; }
}
)
define(TYPEPick_ASN_TYPE,
void $1Pick::operator=($1 scalar)
// Assign scalar to all IntVec-subscripted elements of $1Vec.
{
int i = length();
const int* xp = (*X).pt();
$1 c = scalar;
$1Vec& D = *V;
while (i--) { D[*xp++] = c; }
}
)
define(TYPESlct_ASN_TYPEVec,
void $1Slct::operator=(const $1Vec& U)
// Assign a $1Vec to BitVec-selected elements of $1Vec.
{
if (U.length() != sum(*B)) U.selectErr(*B);
$1* dp = V->pt();
const $1* sp = U.pt();
BITVECSCAN(*B, U.length(), *dp = *sp++; dp++)
}
)
define(TYPESlct_ASN_TYPEPick,
void $1Slct::operator=(const $1Pick& s)
// Assign IntVec-subscripted elements of $1Vec to BitVec-selected elements of $1Vec.
{
if (s.length() != sum(*B)) s.X->selectErr(*B);
$1* dp = V->pt();
const int* xp = (*s.X).pt();
$1Vec& W = *s.V;
BITVECSCAN(*B, length(), *dp = W[*xp++]; dp++)
}
)
define(TYPESlct_ASN_TYPESlct,
void $1Slct::operator=(const $1Slct& s)
// Assign BitVec-selected elements of $1Vec to BitVec-selected elements of $1Vec.
{
$1Vec T;
T = (*s.V)[*s.B];
(*V)[*B] = T;
}
)
define(TYPESlct_ASN_TYPESlice,
void $1Slct::operator=(const $1Slice& s)
// Assign $1Vec slice to BitVec-selected elements of $1Vec.
{
if (s.length() != sum(*B)) s.selectErr(*B);
$1* dp = V->pt();
const $1* sp = s.pt();
int j = s.stride();
BITVECSCAN(*B, length(), { *dp = *sp; sp += j; }; dp++)
}
)
define(TYPESlct_ASN_TYPE,
void $1Slct::operator=($1 scalar)
// Assign scalar to all BitVec-selected elements of $1Vec.
{
$1* dp = V->pt();
$1 c = scalar;
BITVECSCAN(*B, length(), *dp = c; dp++)
}
)
define(TYPESlice_APPLY_FUN__TYPEVec,
$1Vec $1Slice::apply(mathFunTy f) const
// Apply function to each element of vector slice
{
int i = l;
$1Vec T(i);
$1* sp = p;
$1* dp = T.pt();
int j = k;
while (i--) { *dp++ = f(*sp); sp += j; }
return T;
}
)
define(FRIEND_abs_TYPESlice,
$1Vec abs(const $1Slice& s)
// Absolute value of $1Vec slice.
{
int i = s.length();
$1Vec T(i);
const $1* sp = s.pt();
$1* dp = T.pt();
int j = s.stride();
while (i--) { *dp++ = ABS(*sp); sp += j; }
return T;
}
)
define(FRIEND_atan2_TYPESlice_TYPESlice,
$1Vec atan2(const $1Slice& u,const $1Slice& v)
// Arctangent of u/v.
{
int i = u.length();
if (i != v.length()) u.lengthErr(v);
$1Vec T(i);
const $1* up = u.pt();
const $1* vp = v.pt();
$1* dp = T.pt();
int uj = u.stride();
int vj = v.stride();
while (i--) { *dp++ = $2(*up,*vp); up += uj; vp += vj; }
return T;
}
)
define(FRIEND_pow_TYPESlice_TYPESlice,
$1Vec pow(const $1Slice& u,const $1Slice& v)
// u to the v power.
{
int i = u.length();
if (i != v.length()) u.lengthErr(v);
$1Vec T(i);
const $1* up = u.pt();
const $1* vp = v.pt();
$1* dp = T.pt();
int uj = u.stride();
int vj = v.stride();
while (i--) { *dp++ = $2(*up,*vp); up += uj; vp += vj; }
return T;
}
)
define(FRIEND_cumsum_TYPESlice,
$1Vec cumsum(const $1Slice& s)
// Cumulative sum of $1Vec slice.
// Note: V == delta(cumsum(V)) == cumsum(delta(V))
{
unsigned i = s.length();
$1Vec T(i);
const $1* sp = s.pt();
$1* dp = T.pt();
$1 c = 0;
int j = s.stride();
while (i--) { *dp++ = c += *sp; sp += j; }
return T;
}
)
define(FRIEND_delta_TYPESlice,
$1Vec delta(const $1Slice& s)
// Element differences of $1Vec slice.
// Note: V == delta(cumsum(V)) == cumsum(delta(V))
{
unsigned i = s.length();
$1Vec T(i);
const $1* sp = s.pt();
$1* dp = T.pt();
$1 c = 0;
int j = s.stride();
while (i--) { *dp++ = *sp - c; c = *sp; sp += j; }
return T;
}
)
define(FRIEND_dot_TYPESlice_TYPESlice,
$1 dot(const $1Slice& u,const $1Slice& v)
// Vector dot product.
{
int i = u.length();
if (i != v.length()) u.lengthErr(v);
$1 t =0;
const $1* up = u.pt();
const $1* vp = v.pt();
int uj = u.stride();
int vj = v.stride();
while (i--) { t += *up * *vp; up += uj; vp += vj; }
return t;
}
)
define(FRIEND_max_TYPESlice,
int max(const $1Slice& s)
// Index of maximum element.
{
if (s.length() == 0) s.V->emptyErr("max");
const $1* sp = s.pt();
$1 t = *sp;
int j = s.stride();
int x = 0;
for (int i =0; i<s.length(); i++) {
if (*sp > t) { t = *sp; x = i; }
sp += j;
}
return x;
}
)
define(FRIEND_min_TYPESlice,
int min(const $1Slice& s)
// Index of minimum element.
{
if (s.length() == 0) s.V->emptyErr("min");
const $1* sp = s.pt();
$1 t = *sp;
int j = s.stride();
int x = 0;
for (int i =0; i<s.length(); i++) {
if (*sp < t) { t = *sp; x = i; }
sp += j;
}
return x;
}
)
define(FRIEND_prod_TYPESlice,
$1 prod(const $1Slice& s)
// Product of $1Vec slice elements.
{
int i = s.length();
const $1* sp = s.pt();
$1 t = 1;
int j = s.stride();
while (i--) { t *= *sp; sp += j; }
return t;
}
)
define(FRIEND_reverse_TYPESlice,
$1Vec reverse(const $1Slice& s)
// Reverse vector elements.
{
int i = s.length();
$1Vec T(i);
const $1* sp = s.pt();
$1* dp = &T(i);
int j = s.stride();
while (i--) { *(--dp) = *sp; sp += j; }
return T;
}
)
define(FRIEND_sum_TYPESlice,
$1 sum(const $1Slice& s)
// Sum of vector elements.
{
int i = s.length();
const $1* sp = s.pt();
$1 t = 0;
int j = s.stride();
while (i--) { t += *sp; sp += j; }
return t;
}
)
define(FRIEND_acos_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_asin_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_atan_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_ceil_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_cos_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_cosh_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_exp_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_floor_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_log_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_sin_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_sinh_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_sqrt_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_tan_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })
define(FRIEND_tanh_TYPESlice,$1Vec $2(const $1Slice& V) { return V.apply($2); })